package algorithms.implementation

/*
 * [Grading Students](https://www.hackerrank.com/challenges/grading)
 * Complete the gradingStudents function below.
 */
fun gradingStudents(grades: Array<Int>): Array<Int> {
    return Array(grades.size) {
        val v = grades[it]
        when {
            v < 38 -> v
            v % 5 > 2 -> (v + 5 - v % 5)
            else -> v
        }
    }
}

// Complete the countApplesAndOranges function below.
fun countApplesAndOranges(s: Int, t: Int, a: Int, b: Int, apples: Array<Int>, oranges: Array<Int>) {
    val aS = s - a
    val aT = t - a
    val appleCount = apples.count { it in aS..aT }
    val bS = s - b
    val bT = t - b
    val orangeCount = oranges.count { it in bS..bT }

    println(appleCount)
    println(orangeCount)
}

/**
 * [Kangaroo](https://www.hackerrank.com/challenges/kangaroo)
 */
// Complete the kangaroo function below.
fun kangaroo(x1: Int, v1: Int, x2: Int, v2: Int): String {
    if (v1 <= v2) {
        return "NO"
    }
    val delta = x2 - x1
    val canReach = delta % kotlin.math.abs(v1 - v2) == 0

    return if (canReach) "YES" else "NO"
}

/*
 * [Between Two Sets](https://www.hackerrank.com/challenges/between-two-sets)
 * Complete the getTotalX function below.
 */
fun getTotalX(a: Array<Int>, b: Array<Int>): Int {
    val range = a.max()!!..b.min()!!
    var ans = 0

    for (i in range) {
        if (a.all { i % it == 0 } && b.all { it % i == 0 }) {
            ans++
        }
    }
    return ans
}

/**
 * [Breaking the Records](https://www.hackerrank.com/challenges/breaking-best-and-worst-records)
 */
// Complete the breakingRecords function below.
fun breakingRecords(scores: Array<Int>): Array<Int> {
    var max = scores[0]
    var min = scores[0]
    var maxCount = 0
    var minCount = 0

    scores.forEach {
        if (it > max) {
            maxCount++
            max = it
        } else if (it < min) {
            minCount++
            min = it
        }
    }
    return arrayOf(maxCount, minCount)
}

/**
 * [Birthday Chocolate](https://www.hackerrank.com/challenges/the-birthday-bar)
 */
// Complete the solve function below.
fun solve(s: Array<Int>, d: Int, m: Int): Int {
    var ans = 0
    var sum = s.take(m).sum()
    if (sum == d) {
        ans++
    }
    for (i in 0 until s.size - m) {
        sum -= s[i]
        sum += s[i + m]
        if (sum == d) {
            ans++
        }
    }

    return ans
}

/**
 * [Divisible Sum Pairs](https://www.hackerrank.com/challenges/divisible-sum-pairs)
 */
// Complete the divisibleSumPairs function below.
fun divisibleSumPairs(n: Int, k: Int, ar: Array<Int>): Int {
    var ans = 0
    for (i in 0 until n - 1) {
        for (j in i + 1 until n) {
            if ((ar[i] + ar[j]) % k == 0) {
                ans++
            }
        }
    }
    return ans
}

/**
 * [Migratory Birds](https://www.hackerrank.com/challenges/migratory-birds)
 */
// Complete the migratoryBirds function below.
fun migratoryBirds(arr: Array<Int>): Int {
    val groupBy = arr.groupBy { it }
    var ans = groupBy.keys.first()
    var max = 0

    groupBy.forEach { t, u ->
        if (u.size > max) {
            ans = t
            max = u.size
        } else if (u.size == max) {
            if (t < ans) {
                ans = t
            }
        }
    }

    return ans
}

/**
 * [Day of the Programmer](https://www.hackerrank.com/challenges/day-of-the-programmer)
 */
fun dayOfTheProgrammer(year: Int): String {
    if (year == 1918)
        return "26.09.1918"

    fun isLeapYear(y: Int): Boolean {
        return when {
            y % 400 == 0 -> true
            (y < 1918) && (y % 4 == 0) -> true
            y % 100 == 0 -> false
            y % 4 == 0 -> true
            else -> false
        }
    }

    val d = if (isLeapYear(year)) 12 else 13

    return "${d.toString().padStart(2, '0')}.09.${year.toString().padStart(4, '0')}"
}

/**
 * [Bon Appétit](https://www.hackerrank.com/challenges/bon-appetit)
 */
// Complete the bonAppetit function below.
fun bonAppetit(bill: Array<Int>, k: Int, b: Int) {
    val total = (bill.sum() - bill[k]) / 2
    if (b > total) {
        println(b - total)
    } else {
        println("Bon Appetit")
    }
}

/**
 * [Sock Merchant](https://www.hackerrank.com/challenges/sock-merchant)
 */
// Complete the sockMerchant function below.
fun sockMerchant(n: Int, ar: Array<Int>): Int {
    return ar.groupBy { it }.map { it.value.size / 2 }.sum()
}

/*
 * [Drawing Book](https://www.hackerrank.com/challenges/drawing-book)
 * Complete the pageCount function below.
 */
fun pageCount(n: Int, p: Int): Int {
    val pStart = p / 2
    val pEnd = (n - p + (n + 1) % 2) / 2

    return kotlin.math.min(pStart, pEnd)
}

/**
 * [Counting Valleys](https://www.hackerrank.com/challenges/counting-valleys)
 */
// Complete the countingValleys function below.
fun countingValleys(n: Int, s: String): Int {
    var ans = 0
    var height = 0
    s.forEach {
        when (it) {
            'U' -> {
                height++
                if (height == 0) {
                    ans++
                }
            }
            'D' -> height--
        }
    }

    return ans
}

/*
 * [Electronics Shop](https://www.hackerrank.com/challenges/electronics-shop)
 * Complete the getMoneySpent function below.
 */
fun getMoneySpent(keyboards: Array<Int>, drives: Array<Int>, b: Int): Int {
    if ((keyboards.min()!! + drives.min()!!) > b) {
        return -1
    }
    drives.sort()
    var ans = 1
    var bill: Int
    keyboards.forEach {
        for (drive in drives) {
            bill = it + drive
            if (bill <= b) {
                if (bill > ans) {
                    ans = bill
                }
            } else {
                break
            }
        }
    }

    return ans
}

/**
 * [Cats and a Mouse](https://www.hackerrank.com/challenges/cats-and-a-mouse)
 */
// Complete the catAndMouse function below.
fun catAndMouse(x: Int, y: Int, z: Int): String {
    val deltaA = kotlin.math.abs(x - z)
    val deltaB = kotlin.math.abs(y - z)
    return when {
        deltaA < deltaB -> "Cat A"
        deltaA == deltaB -> "Mouse C"
        else -> "Cat B"
    }
}

/**
 * [Picking Numbers](https://www.hackerrank.com/challenges/picking-numbers)
 */
// Complete the pickingNumbers function below.
fun pickingNumbers(a: Array<Int>): Int {
    val map = HashMap<Int, Int>()
    a.forEach { map[it] = map.getOrDefault(it, 0) + 1 }
    var ans = 0
    var temp: Int
    val keys = map.keys.sorted()
    for (key in keys) {
        temp = map[key]!! + map.getOrDefault(key + 1, 0)
        if (temp > ans) {
            ans = temp
        }
    }

    return ans
}

/**
 * [The Hurdle Race](https://www.hackerrank.com/challenges/the-hurdle-race)
 */
// Complete the hurdleRace function below.
fun hurdleRace(k: Int, height: Array<Int>): Int {
    val max = height.max()!!
    return if (max < k) 0 else (max - k)
}